const express = require("express");
const router = express.Router();
const { Op } = require("sequelize");
const { success, failure } = require("../../utils/response");
const { NotFound } = require('http-errors');
const { Article } = require("../../models");
const { getKey,setKey, redisClient, getKeysByPattern, delKey} = require("../../utils/redis")

// 查询全部数据
router.get("/", async (req, res) => {
  try {
    // 获取查询参数
    const query = req.query;
    // 获取分页参数
    const pageIndex = Math.abs(Number(query.pageIndex)) || 1; // 当前页码，默认为1
    const pageSize = Math.abs(Number(query.pageSize)) || 10; // 每页条数，默认为10
    const offset = (pageIndex - 1) * pageSize; // 偏移量

    // 定义查询条件
    const condition = {
      order: [["id", "DESC"]],
      limit: pageSize, // 每页条数
      offset: offset, // 偏移量
    };
    // 查询数据 findAndCountAll 会返回两个对象 一个是 count 一个是rows
    const { count, rows } = await Article.findAndCountAll(condition);
    // 返回查询结果
    const data = {
      pagination: {
        total: count, // 总条数
        pageIndex,
        pageSize, // 每页条数
      },
      articles: rows,
    };
    success(res, "查询文章列表成功", data);
  } catch (error) {
    // 返回错误信息
    failure(res, error);
  }
});

// 查询文章列表
router.get("/redis",async(req,res)=>{
  try {
    const query = req.query
    const pageIndex = Number(Math.abs(query.pageIndex))|| 1
    const pageSize = Number(Math.abs(query.pageSize)) || 10
    const offset = (pageIndex-1) * pageSize

    // 定义带有[当前页码]和[每页条数]的 cachekey 作为缓存的键
    const cacheKey = `articles:${pageIndex}:${pageSize}`;
    let data = await getKey(cacheKey)
    if(data){
      return success(res,'查询文章列表成功',data)
    }

    const condition = {
      attributes:{exclude:['content']},
      order:[["id","DESC"]],
      limit:pageSize,
      offset
    }

    const {count,rows} = await Article.findAndCountAll(condition)
    data = {
      articles:rows,
      pagination:{
        total:count,
        pageIndex,
        pageSize
      }
    }
    await setKey(cacheKey,data)
    success(res,'查询文章列表成功',data)
  } catch (error) {
    failure(res,error)
  }
})

// 添加文章数据
router.post("/", async (req, res) => {
  try {
    const body = filterBody(req);

    // 创建文章
    const article = await Article.create(body);

    // 返回结果
    success(res, "添加文章成功", { article }, 201);
  } catch (error) {
    failure(res, error);
  }
});

// 删除文章数据
router.delete("/:id", async (req, res) => {
  try {
    const article = await getArticle(req);
    // 删除数据
    await article.destroy();
    // 返回结果
    success(res, "删除文章成功");
  } catch (error) {
    failure(res, error);
  }
});

// 更新文章数据
router.put("/:id", async (req, res) => {
  try {
    const body = filterBody(req);

    const article = await getArticle(req);
    // 更新数据
    await article.update(body);
    // 返回结果
    success(res, "更新文章成功", { article });
  } catch (error) {
    failure(res, error);
  }
});

// 模糊查询搜素
router.get("/search", async (req, res) => {
  try {
    // 获取查询参数
    const query = req.query;

    // 定义查询条件
    const condition = {
      where: {},
      order: [["id", "DESC"]],
    };
    // 如果有title查询参数，就添加到where条件中
    if (query.title) {
      condition.where.title = {
        [Op.like]: `%${query.title}%`,
      };
    }

    // 查询数据
    const articles = await Article.findAll(condition);
    // 返回查询结果
    success(res, "模糊查询成功", { articles });
  } catch (error) {
    failure(res, error);
  }
});

// 查询单个文章数据
router.get("/:id", async (req, res) => {
  try {
    const article = await getArticle(req);
    // 返回查询结果
    success(res, "查询文章详情成功", { article });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 公共方法：白名单过滤
 * @param {*} req
 * @returns
 */
function filterBody(req) {
  return {
    title: req.body.title,
    content: req.body.content,
  };
}

/**
 * 公共方法：查询当前文章
 * @param {*} req
 * @returns
 */
async function getArticle(req) {
  const { id } = req.params;

  const article = await Article.findByPk(id);
  if (!article) {
    throw new NotFound("文章未找到");
  }
  return article;
}

/**
 * 清除缓存
 */
async function clearCache() {
  // 清除所有文章列表缓存
  const keys = await getKeysByPattern('articles:*');
  if(keys.length !==0){
    await delKey(keys)
  }
}

module.exports = router;
